/******************************************************************************
 * The contents of this file are subject to the   JDI License  Version 1.0
 * ("License"); You may not use this file except in compliance with the License
 * Software distributed under the License is distributed on an  "AS IS"  basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 * The Initial Developer of the Original Code is 陈慧然. Portions created by 
 * 陈慧然 are Copyright 陈慧然.
 * All Rights Reserved.
 *
 *              Contact john_holen@163.com for licensing alternatives.
 *
 *****************************************************************************/

package org.peony.config;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.peony.db.base.PeonyDataSource;
import org.peony.exceptions.ConfigException;
import org.peony.models.MApplicationConfig;
import org.peony.models.MDBConfig;
import org.peony.standard.db.SAJDBCConnectionProviderFactory;
import org.peony.standard.db.SAJTAConnectionProviderFactory;
import org.peony.standard.unvarying.cfgs.ApplicationConfigParamNames;
import org.peony.standard.unvarying.cfgs.ApplicationServerConfigPropertiesKeys;
import org.peony.standard.unvarying.db.TranscationType;
import org.peony.tools.PeonyLogger;
import org.peony.tools.StringUtil;

/**
 * 
 * 
 * @author 陈慧然
 * @version Id: PeonyContextListener.java, v 0.000 2008-7-5 下午05:31:54 陈慧然 Exp
 */
public class PeonyContextListener implements ServletContextListener {
	private ServletContext context;
	private PeonyLogger logger = PeonyLogger.getInstance();

	public void contextDestroyed(ServletContextEvent event) {
		logger.info(this.getClass().getName()
				+ ".contextDestroyed(ServletContextEvent)开始工作,销毁工作环境");
		this.context = null;
		logger.info(this.getClass().getName()
				+ ".contextDestroyed(ServletContextEvent)结束工作,工作环境被销毁");
	}

	public void contextInitialized(ServletContextEvent event) {
		logger.info(this.getClass().getName()
				+ ".contextInitialized(ServletContextEvent)开始工作,建立工作环境");
		this.context = event.getServletContext();
		setApplicationContext();
		logger.info(this.getClass().getName()
				+ ".contextInitialized(ServletContextEvent)结束工作,工作环境被建立");
	}
	
	

	// 加载应用基本信息
	private void setApplicationContext() {
		logger.info("正在加载配置信息。");
		String location = context
				.getInitParameter(ApplicationConfigParamNames.ApplicationConfigLocation);
		InputStream configFile = context.getResourceAsStream(location);
		Document document;
		SAXReader reader = new SAXReader();
		try{
			document = reader.read(configFile);
			configFile.close();	
			Element root = document.getRootElement();
			//加载数据库设置
			List dbConfigList = root.elements(ApplicationServerConfigPropertiesKeys.DOMAIN_DATASOURCES);
			if(dbConfigList == null || dbConfigList.isEmpty() || dbConfigList.size() != 1)
				throw new ConfigException(ConfigException.DBCONFIGERROR);
			Element dbConfig = (Element)dbConfigList.get(0);
			setDbConfig(dbConfig);
			// 加载应用基本设置
			List appConfigList = root.elements(ApplicationServerConfigPropertiesKeys.DOMAIN_APPCONFIG);
			if(appConfigList == null || appConfigList.isEmpty() || appConfigList.size() != 1)
				throw new ConfigException(ConfigException.APPCONFIGERROR);
			Element appConfig = (Element)appConfigList.get(0);
			setAppConfig(appConfig);
		}catch(Exception e){
			throw new ConfigException(e);
		}
		logger.info("加载配置信息完毕。");
	}

	private void setAppConfig(Element appConfig){
		logger.info("正在加载应用服务配置信息。");
		logger.info("加载应用服务配置信息完毕。");
	}
	
	// 设置数据库配置信息
	private void setDbConfig(Element dbConfig){
		logger.info("正在加载数据源配置信息。");
		// 全局事务类型
		String transactionType = dbConfig.attribute(ApplicationServerConfigPropertiesKeys.DOMAIN_DATASOURCES_TRANSACTIONTYPE).getValue();
		// 从XML文件获得数据源列表
		List dataSources = dbConfig.elements(ApplicationServerConfigPropertiesKeys.DOMAIN_DATASOURCE);
		if(dataSources == null || dataSources.size() < 1)
			throw new ConfigException(ConfigException.DBCONFIGERROR);
		Map<String,PeonyDataSource> peonyDataSources = new HashMap<String,PeonyDataSource>();
		
		// 循环数据源列表，以完成数据源配置
		for (Iterator iterator = dataSources.iterator(); iterator.hasNext();) {
			Element dataSource = (Element) iterator.next();
			// 数据源名称
			String dataSourceName = dataSource.attributeValue(ApplicationServerConfigPropertiesKeys.DOMAIN_DATASOURCE_NAME);
			// 数据源类型－字符
			String dataSourceType_String = dataSource.attributeValue(ApplicationServerConfigPropertiesKeys.DOMAIN_DATASOURCE_DBMSTYPE);
			// 连接提供者类路径
			String className = dataSource.elementTextTrim(ApplicationServerConfigPropertiesKeys.DOMAIN_DATASOURCE_CONNECTIONPROVIDERFACTORY);
			// 数据源事务类别
			String dataSource_transactionType = dataSource.attributeValue(ApplicationServerConfigPropertiesKeys.DOMAIN_DATASOURCE_TRANSACTIONTYPE);
			// 数据源类型
			int dataSourceType;
			try{
				dataSourceType = Integer.parseInt(dataSourceType_String);
			}catch(Exception e){
				throw new ConfigException(ConfigException.ERRORDBMSTYPE);
			}
			
			PeonyDataSource peonyDataSource = new PeonyDataSource();
			// 根据全局事务类型进行数据源配置
			if(transactionType.equalsIgnoreCase(TranscationType.JDBC)){
				if(StringUtil.isEmpty(dataSource_transactionType) || dataSource_transactionType.equals(TranscationType.JDBC)){
					peonyDataSource.setDbmsType(dataSourceType);
					peonyDataSource.setDataSourceTransactionType(TranscationType.JDBC);
					peonyDataSource.setDataSourceProviderClassName(className);
					peonyDataSources.put(dataSourceName, peonyDataSource);
				}else
					throw new ConfigException(ConfigException.TRASCATIONTYPEISERROR);
			}
			
			else if(transactionType.equalsIgnoreCase(TranscationType.JTA)){
				if(StringUtil.isEmpty(dataSource_transactionType) || dataSource_transactionType.equals(TranscationType.JTA)){
					peonyDataSource.setDbmsType(dataSourceType);
					peonyDataSource.setDataSourceTransactionType(TranscationType.JTA);
					peonyDataSource.setDataSourceProviderClassName(className);
					peonyDataSources.put(dataSourceName, peonyDataSource);
				}else
					throw new ConfigException(ConfigException.TRASCATIONTYPEISERROR);
			}
			
			else if(transactionType.equalsIgnoreCase(TranscationType.ALL)){
				if(StringUtil.isNotEmpty(dataSource_transactionType) && dataSource_transactionType.equals(TranscationType.JDBC)){
					peonyDataSource.setDbmsType(dataSourceType);
					peonyDataSource.setDataSourceTransactionType(dataSource_transactionType);
					peonyDataSource.setDataSourceProviderClassName(className);
					peonyDataSources.put(dataSourceName, peonyDataSource);
				}else if(StringUtil.isNotEmpty(dataSource_transactionType) && dataSource_transactionType.equals(TranscationType.JTA)){
					peonyDataSource.setDbmsType(dataSourceType);
					peonyDataSource.setDataSourceTransactionType(dataSource_transactionType);
					peonyDataSource.setDataSourceProviderClassName(className);
					peonyDataSources.put(dataSourceName, peonyDataSource);
				}else
					throw new ConfigException(ConfigException.TRASCATIONTYPEISERROR);
			}
			
			else
				throw new ConfigException(ConfigException.TRASCATIONTYPEISERROR);
			
			// 设置数据库配置
			MDBConfig.setModel(peonyDataSources, transactionType);
		}
		logger.info("加载数据源配置信息完毕。");
	}
}
